package com.ease.dao.statement.factory;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;

import com.ease.dao.statement.provider.ClassPathXmlStatementProvider;
import com.ease.dao.statement.util.NamedStatementUtil;

/**
 *
 * @author nathanleewei
 *
 */
public class XmlFreeMarkerNamedStatementFactory extends AbstractFreeMarkerNamedStatementFactory {

	private static final transient Log log = LogFactory.getLog(XmlFreeMarkerNamedStatementFactory.class);

	private Resource[] locations;

	private static final SAXReader saxReader = new SAXReader();

	private ClassPathXmlStatementProvider classPathXmlStatementProvider;

	public static NamedStatementFactory newInstance(Class<?> namespaceClass) {
		// String namespace = namespaceClass.getSimpleName();

		String path = ClassUtils.classPackageAsResourcePath(namespaceClass) + '/' + namespaceClass.getSimpleName() + ".statement.xml";
		Resource resource = new ClassPathResource(path);
		XmlFreeMarkerNamedStatementFactory namedStatementXmlFreeMarkerFactory = new XmlFreeMarkerNamedStatementFactory();
		namedStatementXmlFreeMarkerFactory.setLocations(new Resource[] { resource });
		namedStatementXmlFreeMarkerFactory.init();
		return namedStatementXmlFreeMarkerFactory;
	}

	protected String doGetNamedStatement(String name, Object parameter) {
		// if (null == classPathXmlStatementProvider) {
		// classPathXmlStatementProvider = new ClassPathXmlStatementProvider();
		// classPathXmlStatementProvider.setLocations(locations);
		// }
		// return classPathXmlStatementProvider.getStatement(name);
		return statements.get(name);
	}

	public void init() {
		this.init(null);
	}

	// TODO
	public void init(String namespace) {
		if (null == locations) {
			return;
		}
		InputStream is = null;
		Document document = null;
		for (Resource location : locations) {
			try {
				is = location.getInputStream();
			} catch (IOException e1) {
				log.error(location.getDescription() + " not found");
			}

			if (null == is) {
				return;
			}

			try {
				document = saxReader.read(is);
			} catch (DocumentException e) {
				log.error(location.getDescription() + "document not found");
			}
			if (null == document) {
				return;
			}

			Element rootElement = document.getRootElement();
			namespace = (notEmpty(namespace)) ? namespace : rootElement.attributeValue("namespace");
			for (Object statementObject : rootElement.elements("statement")) {
				Element element = (Element) statementObject;
				String name = element.attributeValue("name");
				String statement = transform(element.getTextTrim());

				putStatement(NamedStatementUtil.statementName(namespace, name), statement);
			}
		}
	}

	/**
	 * @return the classPathXmlStatementProvider
	 */
	public ClassPathXmlStatementProvider getClassPathXmlStatementProvider() {
		return classPathXmlStatementProvider;
	}

	/**
	 * @param classPathXmlStatementProvider
	 *            the classPathXmlStatementProvider to set
	 */
	public void setClassPathXmlStatementProvider(ClassPathXmlStatementProvider classPathXmlStatementProvider) {
		this.classPathXmlStatementProvider = classPathXmlStatementProvider;
	}

	/**
	 * @return the locations
	 */
	public Resource[] getLocations() {
		return locations;
	}

	/**
	 * @param locations
	 *            the locations to set
	 */
	public void setLocations(Resource[] locations) {
		this.locations = locations;
	}

}
